﻿using System;
using System.Collections.Generic;
using System.Linq;
using ActionLogic;
using BehaviorModel.Block;
using BehaviorModel.Block.Generator;
using BehaviorModel.Block.ServiceChannel;
using log4net;

namespace BehaviorModel
{
    public class BlockController : IBlockController
    {
        private static readonly IBlockController _instance = new BlockController();

        private List<IBlock> _blocks;

        private BlockController()
        {
            _blocks = new List<IBlock>();
        }

        public static IBlockController GetInstance()
        {
            return _instance;
        }

        public IBlock this[Guid id]
        {
            get { return _blocks.Find(x => x.Id == id); }
        }

        public void AddBlock(IBlock block)
        {
            _blocks.Add(block);
            SubscribeBlockOnActionExecuted(block);
        }

        private void SubscribeBlockOnActionExecuted(IBlock block)
        {
            if (block is IExecutable)
            {
                var actionBlock = block as IExecutable;
                actionBlock.OnActionExecuted += (sender) => ActionExecutor.GetInstance().Add(sender);
            }
        }

        public void RemoveBlock(IBlock block)
        {
            _blocks.Remove(block);
        }

        public void ClearBlocks()
        {
            _blocks.Clear();
        }

        public void Connect(ISenderBlock senderBlock, IReceiverBlock receiverBlock)
        {
            senderBlock.ConnectReceiverBlock(receiverBlock);
        }

        public void Disconnect(ISenderBlock senderBlock, IReceiverBlock receiverBlock)
        {
            senderBlock.DisconnectReceiverBlock(receiverBlock);
        }
        
        public void InitBlocks()
        {
            _blocks.ForEach(block => block.Initialize());
        }
     
        public List<IServiceChannel> GetServiceChannels()
        {
            return _blocks.FindAll(b => b.Type == BlockType.ServiceChannel).Cast<IServiceChannel>().ToList();
        }

        public List<IGenerator> GetGenerators()
        {
            return _blocks.FindAll(b => b.Type == BlockType.Generator).Cast<IGenerator>().ToList();
        }

        public void UpdateBlocks()
        {
            _blocks.ForEach(block => block.Statistic.Update());
        }
    }
}